package com.cmdb.common.utils;

import java.util.regex.Pattern;

/**
 * 密码复杂度检测工具类
 * 
 * @author cyq
 */
public class PasswordUtils {
    
    /**
     * 检测密码复杂度
     * 
     * @param password 密码
     * @return 检测结果
     */
    public static PasswordCheckResult checkPasswordComplexity(String password) {
        PasswordCheckResult result = new PasswordCheckResult();
        
        if (StringUtils.isEmpty(password)) {
            result.setValid(false);
            result.setMessage("密码不能为空");
            return result;
        }
        
        // 检查密码长度
        if (password.length() < 8) {
            result.setValid(false);
            result.setMessage("密码长度不能少于8位");
            return result;
        }
        
        if (password.length() > 20) {
            result.setValid(false);
            result.setMessage("密码长度不能超过20位");
            return result;
        }
        
        // 检查是否包含大写字母
        if (!Pattern.compile("[A-Z]").matcher(password).find()) {
            result.setValid(false);
            result.setMessage("密码必须包含至少一个大写字母");
            return result;
        }
        
        // 检查是否包含小写字母
        if (!Pattern.compile("[a-z]").matcher(password).find()) {
            result.setValid(false);
            result.setMessage("密码必须包含至少一个小写字母");
            return result;
        }
        
        // 检查是否包含数字
        if (!Pattern.compile("\\d").matcher(password).find()) {
            result.setValid(false);
            result.setMessage("密码必须包含至少一个数字");
            return result;
        }
        
        // 检查是否包含特殊字符
        if (!Pattern.compile("[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>/?]").matcher(password).find()) {
            result.setValid(false);
            result.setMessage("密码必须包含至少一个特殊字符(!@#$%^&*()_+-=[]{}|;':\",./<>?)");
            return result;
        }
        
        // 检查是否包含连续字符
        if (hasConsecutiveChars(password)) {
            result.setValid(false);
            result.setMessage("密码不能包含连续字符(如123、abc、ABC等)");
            return result;
        }
        
        // 检查是否包含重复字符
        if (hasRepeatedChars(password)) {
            result.setValid(false);
            result.setMessage("密码不能包含重复字符(如aaa、111等)");
            return result;
        }
        
        // 检查是否包含键盘序列
        if (hasKeyboardSequence(password)) {
            result.setValid(false);
            result.setMessage("密码不能包含键盘序列(如qwerty、123456等)");
            return result;
        }
        
        // 检查是否包含常见弱密码
        if (isCommonWeakPassword(password)) {
            result.setValid(false);
            result.setMessage("密码不能使用常见弱密码");
            return result;
        }
        
        // 计算密码强度
        int strength = calculatePasswordStrength(password);
        result.setStrength(strength);
        
        if (strength < 60) {
            result.setValid(false);
            result.setMessage("密码强度过低，请使用更复杂的密码");
            return result;
        }
        
        result.setValid(true);
        result.setMessage("密码复杂度符合要求");
        return result;
    }
    
    /**
     * 检查是否包含连续字符
     */
    private static boolean hasConsecutiveChars(String password) {
        for (int i = 0; i < password.length() - 2; i++) {
            char c1 = password.charAt(i);
            char c2 = password.charAt(i + 1);
            char c3 = password.charAt(i + 2);
            
            // 检查数字连续
            if (Character.isDigit(c1) && Character.isDigit(c2) && Character.isDigit(c3)) {
                if (c2 == c1 + 1 && c3 == c2 + 1) {
                    return true;
                }
            }
            
            // 检查字母连续
            if (Character.isLetter(c1) && Character.isLetter(c2) && Character.isLetter(c3)) {
                if (c2 == c1 + 1 && c3 == c2 + 1) {
                    return true;
                }
            }
        }
        return false;
    }
    
    /**
     * 检查是否包含重复字符
     */
    private static boolean hasRepeatedChars(String password) {
        for (int i = 0; i < password.length() - 2; i++) {
            char c1 = password.charAt(i);
            char c2 = password.charAt(i + 1);
            char c3 = password.charAt(i + 2);
            
            if (c1 == c2 && c2 == c3) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 检查是否包含键盘序列
     */
    private static boolean hasKeyboardSequence(String password) {
        String lowerPassword = password.toLowerCase();
        String[] keyboardSequences = {
            "qwerty", "asdfgh", "zxcvbn",
            "123456", "654321", "111111", "000000",
            "password", "admin", "root", "user",
            "abc123", "123abc", "qwe123", "123qwe"
        };
        
        for (String sequence : keyboardSequences) {
            if (lowerPassword.contains(sequence)) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 检查是否为常见弱密码
     */
    private static boolean isCommonWeakPassword(String password) {
        String lowerPassword = password.toLowerCase();
        String[] weakPasswords = {
            "password", "123456", "12345678", "qwerty", "abc123",
            "password123", "admin", "admin123", "root", "root123",
            "user", "user123", "test", "test123", "guest", "guest123",
            "welcome", "welcome123", "login", "login123", "pass", "pass123"
        };
        
        for (String weakPwd : weakPasswords) {
            if (lowerPassword.equals(weakPwd)) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 计算密码强度 (0-100)
     */
    private static int calculatePasswordStrength(String password) {
        int strength = 0;
        
        // 基础分数
        strength += password.length() * 4;
        
        // 字符类型加分
        if (Pattern.compile("[a-z]").matcher(password).find()) {
            strength += 10;
        }
        if (Pattern.compile("[A-Z]").matcher(password).find()) {
            strength += 10;
        }
        if (Pattern.compile("\\d").matcher(password).find()) {
            strength += 10;
        }
        if (Pattern.compile("[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>/?]").matcher(password).find()) {
            strength += 15;
        }
        
        // 字符多样性加分
        int uniqueChars = (int) password.chars().distinct().count();
        strength += uniqueChars * 2;
        
        // 长度加分
        if (password.length() >= 12) {
            strength += 10;
        }
        
        // 上限为100
        return Math.min(strength, 100);
    }
    
    /**
     * 密码检测结果类
     */
    public static class PasswordCheckResult {
        private boolean valid;
        private String message;
        private int strength;
        
        public boolean isValid() {
            return valid;
        }
        
        public void setValid(boolean valid) {
            this.valid = valid;
        }
        
        public String getMessage() {
            return message;
        }
        
        public void setMessage(String message) {
            this.message = message;
        }
        
        public int getStrength() {
            return strength;
        }
        
        public void setStrength(int strength) {
            this.strength = strength;
        }
    }
} 